﻿using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using KinonekoSoftware.Foundation.GraphShape.Avalonia.Interfaces;

namespace GraphShape.Controls
{
    /// <summary>
    /// Edge control.
    /// </summary>
    [PseudoClasses(":highlight", ":semi", ":inedge", "outedge")]
    public class EdgeControl : TemplatedControl, IPoolObject, IDisposable, IHighlightStateSource
    {
        static EdgeControl()
        {
            EdgeProperty            = AvaloniaProperty.Register<EdgeControl,object>(nameof(Edge));
            SourceProperty          = AvaloniaProperty.Register<EdgeControl, VertexControl>(nameof(Source));
            TargetProperty          = AvaloniaProperty.Register<EdgeControl, VertexControl>(nameof(Target));
            RoutePointsProperty     = AvaloniaProperty.Register <EdgeControl, aPoint[]>(nameof(RoutePoints));
            StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner<EdgeControl>(new StyledPropertyMetadata<double>(2.0));
        }

        public void CheckHighlightState()
        {
            var highlightInfo     = GraphElementBehaviour.GetHighlightInfo(this).ToString();
            var semiHighlightInfo = GraphElementBehaviour.GetSemiHighlightInfo(this).ToString();
            var highlight         = GraphElementBehaviour.GetIsHighlighted(this);
            var semiHighlight     = GraphElementBehaviour.GetIsSemiHighlighted(this);

            
            PseudoClasses.Set("highlight", highlight);
            PseudoClasses.Set("semi", semiHighlight);
            
            if (highlight)
            {
               
            }


            if (semiHighlight && semiHighlightInfo == SemiHighlightInfos.InEdge)
            {
                PseudoClasses.Set("inedge", true);
            } 
            else if (semiHighlight && semiHighlightInfo == SemiHighlightInfos.OutEdge)
            {
                PseudoClasses.Set("outedge", true);
            }
            else
            {
                PseudoClasses.Set("inedge", false);
                PseudoClasses.Set("outedge", false);
            }
        }
        
        
        #region Dependency Properties

        #region Source

        /// <summary>
        /// Source vertex.
        /// </summary>
        public VertexControl Source
        {
            get => GetValue(SourceProperty);
            internal set => SetValue(SourceProperty, value);
        }

        /// <summary>
        /// Source vertex dependency property.
        /// </summary>
        [NotNull]
        public static readonly StyledProperty<VertexControl> SourceProperty ;

        #endregion

        #region Target

        /// <summary>
        /// Target vertex.
        /// </summary>
        public VertexControl Target
        {
            get => GetValue(TargetProperty);
            internal set => SetValue(TargetProperty, value);
        }

        /// <summary>
        /// Target vertex dependency property.
        /// </summary>
        [NotNull]
        public static readonly StyledProperty<VertexControl> TargetProperty;

        #endregion

        #region RoutePoints

        /// <summary>
        /// Route points.
        /// </summary>
        public aPoint[] RoutePoints
        {
            get => GetValue(RoutePointsProperty);
            set => SetValue(RoutePointsProperty, value);
        }

        /// <summary>
        /// Route points dependency property.
        /// </summary>
        [NotNull]
        public static readonly StyledProperty<aPoint[]> RoutePointsProperty;

        #endregion

        #region Edge

        /// <summary>
        /// Edge.
        /// </summary>
        public object Edge
        {
            get => GetValue(EdgeProperty);
            set => SetValue(EdgeProperty, value);
        }

        /// <summary>
        /// Edge dependency property.
        /// </summary>
        [NotNull]
        public static readonly StyledProperty<object> EdgeProperty;

        #endregion

        #region StrokeThickness

        /// <summary>
        /// Stroke thickness.
        /// </summary>
        public double StrokeThickness
        {
            get => GetValue(StrokeThicknessProperty);
            set => SetValue(StrokeThicknessProperty, value);
        }

        /// <summary>
        /// Stroke thickness dependency property.
        /// </summary>
        [NotNull]
        public static readonly StyledProperty<double> StrokeThicknessProperty;

        #endregion

        #endregion

        #region IPoolObject

        /// <inheritdoc />
        public void Reset()
        {
            Edge = null;
            RoutePoints = null;
            Source = null;
            Target = null;
        }

        /// <inheritdoc />
        public void Terminate()
        {
            // Nothing to do, there are no unmanaged resources
        }

        /// <inheritdoc />
        public event DisposingHandler Disposing;

        #region IDisposable

        /// <inheritdoc />
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Dispose this object.
        /// </summary>
        /// <param name="disposing">Indicates if called by dispose or finalizer.</param>
        protected virtual void Dispose(bool disposing)
        {
            Disposing?.Invoke(this);
        }

        #endregion

        #endregion
    }
}